<?php

namespace app\modules\agent\controllers;

use app\models\Agent;
use app\models\AgentLog;
use app\models\AgentPackage;
use app\models\Card;
use app\models\CardDispatchForm;
use app\models\Isp;
use app\models\KeyMap;
use app\models\User;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use Yii;
use yii\base\InvalidConfigException;
use yii\data\Pagination;
use yii\db\Expression;
use yii\helpers\Url;
use yii\web\BadRequestHttpException;
use yii\web\NotFoundHttpException;

/**
 * 物联网卡管理
 * Class CardController
 * @package app\modules\agent\controllers
 */
class CardController extends BaseController
{
    /**
     * 套餐列表
     * @return string
     */
    public function actionPackageList()
    {
        $query = AgentPackage::find();
        $query->andWhere(['agent_id' => $this->agent->id]);
        $query->orderBy('id DESC');
        $agentPackageList = $query->all();
        return $this->render('package_list', [
            'agentPackageList' => $agentPackageList,
        ]);
    }

    /**
     * 套餐详情
     * @return string
     * @throws NotFoundHttpException
     */
    public function actionPackageView()
    {
        $id = $this->get('id');
        $agentPackage = AgentPackage::findOne(['id' => $id]);
        if (empty($agentPackage) || $agentPackage->agent_id != $this->agent->id) {
            throw new NotFoundHttpException('没有找到套餐。');
        }
        return $this->render('package_view', [
            'agentPackage' => $agentPackage,
        ]);
    }

    /**
     * 保存套餐销售价AJAX接口
     * @return array
     */
    public function actionSaveSalePrice()
    {
        $id = $this->get('id');
        $agentPackage = AgentPackage::findOne(['id' => $id]);
        if (empty($agentPackage) || $agentPackage->agent_id != $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '没有找到套餐。'];
        }
        $salePrice = $this->get('sale_price');
        if (empty($salePrice) || $salePrice < $agentPackage->cost_price) {
            return ['error' => 'SERVER', 'message' => '价格错误，不能低于成本价。'];
        }
        $agentPackage->sale_price = $salePrice;
        $agentPackage->save();
        return [];
    }

    /**
     * 卡列表
     * @return string
     * @throws BadRequestHttpException
     * @throws NotFoundHttpException
     */
    public function actionList()
    {
        $query = Card::find()->alias('card');
        $query->joinWith('isp isp');
        $query->andWhere(['isp.status' => Isp::STATUS_OK]);
        $searchAgentIdList = [];
        if (!empty($this->get('search_agent'))) {
            /** @var Agent $searchAgent */
            $searchAgent = Agent::find()
                ->andWhere(['username' => $this->get('search_agent')])
                ->one();
            if (empty($searchAgent) || !Agent::checkRelation($this->agent->id, $searchAgent->id)) {
                throw new NotFoundHttpException('没有找到代理商【' . $this->get('search_agent') . '】。');
            } else {
                $searchAgentIdList = [$searchAgent->id];
                if ($this->get('search_sub_agent') == 1) { // 包含下级代理商
                    $searchAgentIdList = array_merge($searchAgentIdList, $searchAgent->getSubAidList());
                }
            } 
        }
        if (empty($searchAgentIdList)) {
            #$searchAgentIdList[] = $this->agent->id;
            /** @var Agent $searchAgent */
            $searchAgent = Agent::find()
                ->andWhere(['id' => $this->agent->id])
                ->one();
            $searchAgentIdList = [$searchAgent->id];
                if ($this->get('search_sub_agent') == 1) { // 包含下级代理商
                    $searchAgentIdList = array_merge($searchAgentIdList, $searchAgent->getSubAidList());
                }
        }
        $query->andWhere(['card.agent_id' => $searchAgentIdList]);
        if (!empty($this->get('search_username'))) {
            /** @var User $searchUser */
            $searchUser = User::find()
                ->andWhere(['username' => $this->get('search_username')])
                ->one();
            if (empty($searchUser) || $searchUser->agent_id != $this->agent->id) {
                throw new NotFoundHttpException('没有找到用户【' . $this->get('search_username') . '】。');
            } else {
                $query->andWhere(['uid' => $searchUser->id]);
            }
        }
        $query->andFilterWhere(['card.status' => $this->get('search_status')]);
        $query->andFilterWhere(['card.iccid' => $this->get('search_iccid')]);
        $query->andFilterWhere(['card.msisdn' => $this->get('search_msisdn')]);
        $query->andFilterWhere(['card.package_id' => $this->get('search_package_id')]);
        $searchEndDayAlert = $this->get('search_end_day_alert');
        if (!empty($searchEndDayAlert)) { // 到期提醒的卡
            $query->andWhere(['>', 'card.term_end_time', 0]);
            $query->andWhere(['<=', 'card.term_end_time', time() + $searchEndDayAlert * 86400]);
        }
        $searchOverload = $this->get('search_overload', 0) == 1;
        if ($searchOverload) {
            $query->joinWith('package package');
            $query->andWhere(new Expression('card.data > package.data'));
        }
        $pagination = new Pagination(['totalCount' => $query->count()]);
        $sortName = $this->get('sort_name', 'card.refresh_time');
        $sortOrder = $this->get('sort_order', 'DESC');
        if (!empty($sortName) && !in_array($sortName, ['card.id', 'card.iccid', 'card.msisdn', 'card.refresh_time', 'card.data', 'card.term_end_time'])) {
            throw new BadRequestHttpException('参数错误。');
        }
        if (!empty($sortOrder) && !in_array($sortOrder, ['ASC', 'DESC'])) {
            throw new BadRequestHttpException('参数错误。');
        }
        $query->orderBy([
            $sortName => ['ASC' => SORT_ASC, 'DESC' => SORT_DESC][$sortOrder],
        ]);
        if ($this->get('export') == 'excel') { // 导出Excel文件
            try {
                $excel = new Spreadsheet();
                $sheet = $excel->setActiveSheetIndex(0);
                foreach ([
                             '编号',
                             '代理商',
                             '用户',
                             '套餐',
                             'ICCID',
                             'MSISDN',
                             'IMSI',
                             '状态',
                             '分配时间',
                             '激活时间',
                             '开关机',
                             '数据用量（本月）',
                             '套餐有效期',
                             '套餐结束时间',
                         ] as $index => $title) {
                    $sheet->setCellValue(chr(65 + $index) . '1', $title);
                }
                $sheet->getStyle('A1:Z1')->applyFromArray(['font' => ['bold' => true], 'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER]]);
                $r = 2;
                /** @var Card $card */
                foreach ($query->each() as $card) {
                    $sheet->setCellValueExplicitByColumnAndRow(1, $r, $card->id, DataType::TYPE_NUMERIC);
                    $sheet->setCellValueExplicitByColumnAndRow(2, $r, empty($card->agent_id) ? '' : $card->agent->username, DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(3, $r, empty($card->uid) ? '' : $card->user->username, DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(4, $r, empty($card->package_id) ? '' : $card->package->name, DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(5, $r, $card->iccid, DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(6, $r, $card->msisdn, DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(7, $r, $card->imsi, DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(8, $r, KeyMap::getValue('card_status', $card->status), DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(9, $r, Yii::$app->formatter->asDatetime($card->dispatch_time), DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(10, $r, Yii::$app->formatter->asDatetime($card->active_time), DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(11, $r, $card->on_off, DataType::TYPE_NUMERIC);
                    $sheet->setCellValueExplicitByColumnAndRow(12, $r, Yii::$app->formatter->asShortSize($card->data), DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(13, $r, $card->term_length . KeyMap::getValue('card_term_length_unit', $card->term_length_unit), DataType::TYPE_STRING);
                    $sheet->setCellValueExplicitByColumnAndRow(14, $r, Yii::$app->formatter->asDatetime($card->term_end_time), DataType::TYPE_STRING);
                    $r++;
                }
                $sheet->freezePane('A2');
                header('Content-Type: application/vnd.ms-excel');
                header('Content-Disposition: attachment;filename="card_' . date('Y-m-d') . '.xls"');
                header('Cache-Control: max-age=0');
                $excelWriter = IOFactory::createWriter($excel, 'Xls');
                $excelWriter->save('php://output');
            } catch (\Exception $e) {
                Yii::error('导出Excel文件时出错：' . $e->getMessage());
                Yii::error($e->getTraceAsString());
                echo $e->getMessage();
            }
            die();
        }
        if ($this->get('export') == 'csv') { // 导出CSV文件
            header('Content-Type: application/vnd.ms-excel;charset=UTF-8');
            header('Content-Disposition: attachment;filename="card_' . date('Y-m-d') . '.csv"');
            header('Cache-Control: max-age=0');
            echo "编号,用户编号,套餐,ICCID,MSISDN,IMSI,状态,分配时间,激活时间,开关机,数据用量（本月）（B）,套餐有效期,套餐结束时间\r\n";
            /** @var Card $card */
            foreach ($query->each() as $card) {
                echo $card->id, ',';
                echo $card->uid, ',';
                echo empty($card->package_id) ? '' : $card->package->name, ',';
                echo $card->iccid, ',';
                echo $card->msisdn, ',';
                echo $card->imsi, ',';
                echo KeyMap::getValue('card_status', $card->status), ',';
                try {
                    echo Yii::$app->formatter->asDatetime($card->dispatch_time), ',';
                } catch (InvalidConfigException $e) {
                    echo ',';
                }
                echo $card->on_off, ',';
                echo $card->data, ',';
                echo $card->term_length, KeyMap::getValue('card_term_length_unit', $card->term_length_unit), ',';
                try {
                    echo Yii::$app->formatter->asDatetime($card->term_end_time);
                } catch (InvalidConfigException $e) {
                }
                echo "\r\n";
            }
            die();
        }
        $query->offset($pagination->offset)->limit($pagination->limit);
        $cardList = $query->all();
        return $this->render('card_list', [
            'agent' => $this->agent->identity,
            'cardList' => $cardList,
            'pagination' => $pagination,
        ]);
    }

    /**
     * 到期提醒卡列表
     * @return string
     * @throws BadRequestHttpException
     * @throws NotFoundHttpException
     */
    public function actionListEndDayAlert()
    {
        return $this->actionList();
    }

    /**
     * 超流量卡列表
     * @return string
     * @throws BadRequestHttpException
     */
    public function actionListOverload()
    {
        return $this->actionList();
    }

    /**
     * 分配用户
     * @return string
     */
    public function actionDispatch()
    {
        $model = new CardDispatchForm();
        $model->setAttributes($this->get());
        $model->source = 'iccid';
        $model->user_type = 'user';
        $model->agent = $this->agent->identity;
        if ($model->load($this->post()) && $model->dispatch()) {
            AgentLog::info($this->agent->id, '分配卡', print_r($model->attributes, true));
            Yii::$app->session->addFlash('success', '分配完成。');
            Yii::$app->session->setFlash('redirect', json_encode([
                'url' => Url::to(['/agent/card/list']),
                'txt' => '卡列表'
            ]));
        }
        return $this->render('card_dispatch', [
            'model' => $model,
        ]);
    }

    /**
     * 刷新卡信息AJAX接口
     * @return array
     */
    public function actionRefresh()
    {
        $id = $this->get('id');
        $card = Card::findOne(['id' => $id]);
        if (empty($card) || $card->agent_id != $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '没有找到卡信息。'];
        }
        try {
            $card->refreshBasic();
            return [];
        } catch (\Exception $e) {
            return ['error' => 'SERVER', 'message' => $e->getMessage()];
        }
    }

    /**
     * 强制设备断开网络，使其重新注册。AJAX接口
     * @return array
     */
    public function actionRestart()
    {
        $id = $this->get('id');
        $card = Card::findOne(['id' => $id]);
        if (empty($card) || $card->agent_id != $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '没有找到卡信息。'];
        }
        if ($card->api_id == 1) {
            $api = new \app\models\jasper\Api($card->isp->data);
            try {
                $resp = $api->SendCancelLocation($card->iccid);
                return ['resp' => $resp];
            } catch (\Exception $e) {
                return ['error' => 'SERVER', 'message' => $e->getMessage()];
            }
        } else {
            return ['error' => 'SERVER', 'message' => '不支持此操作。'];
        }
    }

    /**
     * 设置卡状态AJAX接口
     * @return array
     */
    public function actionSetCardStatus()
    {
        $id = $this->get('id');
        $card = Card::findOne(['id' => $id]);
        if (empty($card) || $card->agent_id != $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '没有找到卡信息。'];
        }
        $status = $this->get('status');
        if (!in_array($status, Card::STATUS_TRANSFORM_MAP[$card->status])) {
            return ['error' => 'SERVER', 'message' => '无法将卡设置为：' . KeyMap::getValue('card_status', $status)];
        }
        try {
            $card->setStatus($status);
            return [];
        } catch (\Exception $e) {
            return ['error' => 'SERVER', 'message' => $e->getMessage()];
        }
    }

    /**
     * 卡详情
     * @return string
     * @throws NotFoundHttpException
     */
    public function actionView()
    {
        $id = $this->get('id');
        $card = Card::findOne(['id' => $id]);
        if (empty($card) || $card->agent_id != $this->agent->id) {
            throw new NotFoundHttpException('没有找到卡信息。');
        }
        return $this->render('card_view', [
            'card' => $card,
        ]);
    }

    /**
     * 回收用户卡AJAX接口
     * @return array
     */
    public function actionRevokeFromUser()
    {
        $id = $this->get('id');
        $card = Card::findOne(['id' => $id]);
        if (empty($card) || $card->agent_id != $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '没有找到卡信息。'];
        }
        if (empty($card->uid)) {
            return ['error' => 'SERVER', 'message' => '此卡没有分配用户。'];
        }
        $card->uid = null;
        $card->save(false);
        return [];
    }

    /**
     * 回收代理商卡AJAX接口
     * @return array
     */
    public function actionRevokeFromAgent()
    {
        $id = $this->get('id');
        $card = Card::findOne(['id' => $id]);
        if (empty($card) || $card->agent_id != $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '没有找到卡信息。'];
        }
        if (empty($card->agent_id)) {
            return ['error' => 'SERVER', 'message' => '此卡没有分配给代理商。'];
        }
        if ($card->agent_id == $this->agent->id) {
            return ['error' => 'SERVER', 'message' => '此卡已经属于您了。'];
        }
        // 回收代理商卡相当于将卡分配给上级代理（如果上级代理没有，则直接设置为null）
        $card->agent_id = $card->agent->pid;
        $card->save(false);
        return [];
    }
}
